home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1995-02-10 | 15.5 KB | 368 lines | [TEXT/.Ob4] |
- Syntax10.Scn.Fnt
- Syntax10b.Scn.Fnt
- InfoElems
- Alloc
- Syntax10.Scn.Fnt
- StampElems
- Alloc
- 10 Feb 95
- FoldElems
- Syntax10.Scn.Fnt
- static Module Modules_ThisMod(CHAR *name, LONGINT length) {
- CHAR fname[128];
- Module m;
- long len;
- LONGINT lens[128];
- LONGINT offset, oldpos;
- INTEGER i, ObjFile, nofEntries;
- CHAR name[40];
- *res = done;
- strcpy (importing, name);
- m = FindModule(name);
- if (m == NULL) {
- strcpy(fname, name); strcat(fname, ".Obj");
- ObjFile = FindFile(fname);
- if (*res == done) {
- GetEOF (ObjFile, &len); if (len > 100000) len = 100000;
- FSRead(ObjFile, &len, objfile); pos = 0;
- if (objfile[0] == '\xF8') {
- FSClose(ObjFile);
- m = LoadModule();
- else if (objfile[0] == '\xF9') {
- Check('\xF9'); Check('1');
- Read2(&nofEntries);
- for (i = 0; i < nofEntries; i ++) {
- ReadName(name); Read4(&lens[i]); Read4(&offset);
- }
- oldpos = pos;
- for (i = 0; i < nofEntries; i ++) {
- SetFPos(ObjFile, 1, oldpos); oldpos += lens[i];
- FSRead(ObjFile, &lens[i], objfile); pos = 0;
- m = LoadModule();
- }
- }
- return m;
- "Title": Packager.Mod
- "Author": Christoph Steindl (CS)
- "Abstract": The packager takes a list of modules and puts them into one package which can
- be loaded at once. The modules presented have to be in the right dependency order, i.e.
- the module imported by the most modules must be first and the top-most module, usually
- the user interface module with commands, must be the last module.
- The loader is modified so that it can load whole packages (i.e. top-most modules with all
- their imported modules) instead of (recursively) loading all the imported modules.
- "Keywords": object file format, package, loader
- "Version": 1
- "From": 11.01.95 10:59:04
- "Until":
- "Changes": The procedure ThisMod in the loader (oberon.c) has been adapted
- adapted Modules_ThisMod
- "Hints": Package = [Table] {ObjFile}.
- Table = 0F9X "1" nofEntries2 {Name Len4 Offset4}.
- Syntax10i.Scn.Fnt
- StampElems
- Alloc
- 10 Feb 95
- FoldElems
- Syntax10.Scn.Fnt
- = RECORD
- name: POINTER TO ARRAY OF CHAR;
- len, offset: LONGINT
- END;
- Syntax10.Scn.Fnt
- = RECORD
- entry: Entry;
- next: QueueElement;
- END;
- Syntax10.Scn.Fnt
- = RECORD
- n: INTEGER;
- head, tail: QueueElement;
- END;
- Syntax8i.Scn.Fnt
- Syntax10.Scn.Fnt
- FoldElems
- Syntax10.Scn.Fnt
- BEGIN
- NEW(q.head); q.n := 0; q.tail := q.head;
- END InitFIFOQueue;
- Syntax10.Scn.Fnt
- BEGIN
- NEW(q.tail.next); q.tail.next.entry := e; q.tail := q.tail.next; INC(q.n);
- END Enqueue;
- Syntax10.Scn.Fnt
- BEGIN
- IF q.head # q.tail THEN
- q.head := q.head.next; DEC(q.n);
- RETURN q.head.entry
- ELSE RETURN NIL END
- END Dequeue;
- Syntax10.Scn.Fnt
- BEGIN RETURN q.head = q.tail END Empty;
- Syntax10.Scn.Fnt
- BEGIN IF q.head # q.tail THEN RETURN q.head.next ELSE RETURN NIL END END First;
- Syntax10.Scn.Fnt
- BEGIN IF (this # q.tail) THEN RETURN this.next ELSE RETURN NIL END END Next;
- PROCEDURE InitFIFOQueue (q: FIFOQueue);
- PROCEDURE (q: FIFOQueue) Enqueue (e: Entry);
- PROCEDURE (q: FIFOQueue) Dequeue (): Entry;
- PROCEDURE (q: FIFOQueue) Empty (): BOOLEAN;
- PROCEDURE (VAR q: FIFOQueueDesc) First (): QueueElement;
- PROCEDURE (VAR q: FIFOQueueDesc) Next (this: QueueElement): QueueElement;
- Syntax10.Scn.Fnt
- FoldElems
- Syntax10.Scn.Fnt
- VAR i: INTEGER;
- BEGIN
- i := 0; WHILE n[i] # 0X DO INC(i) END; NEW(e.name, i + 1); COPY(n, e.name^)
- END SetName;
- Syntax10.Scn.Fnt
- VAR i: INTEGER;
- BEGIN
- i := 0; WHILE (n[i] # 0X) & (n[i] # ".") DO INC(i) END;
- n[i] := "."; n[i + 1] := "O"; n[i + 2] := "b"; n[i + 3] := "j"; n[i + 4] := 0X;
- END AppendObj;
- Syntax10.Scn.Fnt
- VAR i: INTEGER;
- BEGIN
- i := 0; WHILE (n[i] # 0X) & (n[i] # ".") DO INC(i) END; n[i] := 0X;
- END SkipObj;
- PROCEDURE (VAR e: EntryDesc) SetName (VAR n: ARRAY OF CHAR);
- PROCEDURE AppendObj (VAR n: ARRAY OF CHAR);
- PROCEDURE SkipObj (VAR n: ARRAY OF CHAR);
- Syntax8i.Scn.Fnt
- Syntax10.Scn.Fnt
- FoldElems
- Syntax10.Scn.Fnt
- TYPE B2 = ARRAY 2 OF CHAR;
- VAR c: B2;
- BEGIN
- c := SYSTEM.VAL(B2, x); Files.WriteBytes(R, c, 2)
- END WriteInt;
- Syntax10.Scn.Fnt
- TYPE B4 = ARRAY 4 OF CHAR;
- VAR c: B4;
- BEGIN
- c := SYSTEM.VAL(B4, x); Files.WriteBytes(R, c, 4)
- END WriteLInt;
- Syntax10.Scn.Fnt
- VAR b: ARRAY 2 OF CHAR;
- BEGIN
- Files.ReadBytes(R, b, 2); x := SYSTEM.VAL(INTEGER, b)
- END ReadInt;
- Syntax10.Scn.Fnt
- VAR b: ARRAY 4 OF CHAR;
- BEGIN
- Files.ReadBytes(R, b, 4); x:=SYSTEM.VAL(LONGINT, b)
- END ReadLInt;
- (* In order to obtain the expected byte-ordering we have to bypass Files.WriteInt and Files.WriteLInt which would
- invert the byte-ordering. Data files are stored in little endian format, the PowerPC is a big endian machine, the
- compiler generates code for a big endian machine and the loader which reads the packages expects big endian
- data. *)
- PROCEDURE WriteInt (VAR R: Files.Rider; x: INTEGER);
- PROCEDURE WriteLInt (VAR R: Files.Rider; x: LONGINT);
- PROCEDURE ReadInt (VAR R: Files.Rider; VAR x: INTEGER);
- PROCEDURE ReadLInt (VAR R: Files.Rider; VAR x: LONGINT);
- Syntax10b.Scn.Fnt
- Syntax8i.Scn.Fnt
- FoldElems
- Syntax8i.Scn.Fnt
- Syntax10.Scn.Fnt
- VAR ch: CHAR;
- BEGIN
- f := Files.Old(package); IF f = NIL THEN RETURN FALSE END;
- Files.Set(r, f, 0);
- Files.Read(r, ch); IF ch # 0F9X THEN RETURN FALSE END;
- Files.Read(r, ch); IF ch # "1" THEN RETURN FALSE END;
- RETURN TRUE
- END OpenPackage;
- Syntax10.Scn.Fnt
- Syntax8i.Scn.Fnt
- Syntax10.Scn.Fnt
- BEGIN
- fdst := Files.New("Package"); Files.Set(rdst, fdst, 0);
- Files.Write(rdst, 0F9X); Files.Write(rdst, "1");
- currPos := 2; (* position of the rider = number of bytes written *)
- END CreatePackage;
- Syntax10.Scn.Fnt
- BEGIN
- Files.Register(f);
- Files.Rename("Package", package, res);
- END ClosePackage;
- PROCEDURE OpenPackage (VAR package: ARRAY OF CHAR; VAR f: Files.File; VAR r: Files.Rider): BOOLEAN;
- (*Opens the package, reads the tag and the version byte and returns TRUE if successful, otherwise FALSE; the global variables r
- and f are set.*)
- PROCEDURE CreatePackage (VAR fdst: Files.File; VAR rdst: Files.Rider; VAR currPos: LONGINT);
- (*Creates the package "Package", writes the tag and version byte and sets currPos to the position of the rider.*)
- PROCEDURE ClosePackage(f: Files.File; VAR package: ARRAY OF CHAR; VAR res: INTEGER);
- (*Registers the package and renames it to the parameter "package", res is the return-value of the Rename-call.*)
- Syntax10b.Scn.Fnt
- Syntax8i.Scn.Fnt
- FoldElems
- Syntax10.Scn.Fnt
- VAR fsrc, fdst: Files.File; rsrc, rdst: Files.Rider; nofEntries, res: INTEGER; currPos: LONGINT;
- module: ModuleName; e: Entry; qelem: QueueElement; entries: FIFOQueue;
- buf: POINTER TO ARRAY OF CHAR;
- BEGIN
- In.Open; In.Name(module); SkipObj(module);
- NEW(entries); InitFIFOQueue(entries);
- CreatePackage(fdst, rdst, currPos); nofEntries := 0; currPos := currPos + 2; (* for nofEntries *)
- WHILE In.Done DO
- NEW(e); INC(nofEntries);
- e.SetName(module); AppendObj(module); fsrc := Files.Old(module);
- IF fsrc = NIL THEN done := FALSE; RETURN END;
- entries.Enqueue(e); e.len := Files.Length(fsrc);
- currPos := currPos + LEN(e.name^) + 8;
- In.Name(module); SkipObj(module);
- END;
- WriteInt(rdst, nofEntries);
- qelem := entries.First();
- WHILE qelem # NIL DO
- Files.WriteString(rdst, qelem.entry.name^); WriteLInt(rdst, qelem.entry.len);
- WriteLInt(rdst, currPos); currPos := currPos + qelem.entry.len;
- qelem := entries.Next(qelem);
- END;
- WHILE ~entries.Empty() DO
- e := entries.Dequeue();
- COPY(e.name^, module); AppendObj(module);
- fsrc := Files.Old(module); Files.Set(rsrc, fsrc, 0);
- NEW(buf, e.len); Files.ReadBytes(rsrc, buf^, e.len); Files.WriteBytes(rdst, buf^, e.len);
- END;
- ClosePackage(fdst, module, res);
- done := res = 0
- END Compose;
- Syntax10.Scn.Fnt
- Syntax10.Scn.Fnt
- Syntax10i.Scn.Fnt
- VAR inPackage: BOOLEAN; extract, module, package, newPackage: ModuleName;
- i, extrI, nofEntries, res: INTEGER; fsrc, fdst: Files.File; rsrc, rdst: Files.Rider;
- currPos, extrOffset, extrLen, len, copyLen, offset, pos1, pos2: LONGINT;
- buf: POINTER TO ARRAY OF CHAR;
- BEGIN
- In.Open; In.Name(extract); SkipObj(extract); In.Name(package); AppendObj(package);
- In.Name(newPackage); AppendObj(newPackage);
- IF ~OpenPackage(package, fsrc, rsrc) THEN done := FALSE; RETURN END;
- ReadInt(rsrc, nofEntries); inPackage := FALSE; extrI := 1;
- WHILE ~inPackage & (extrI <= nofEntries) DO
- pos1 := Files.Pos(rsrc);
- Files.ReadString(rsrc, module); ReadLInt(rsrc, extrLen); ReadLInt(rsrc, extrOffset);
- pos2 := Files.Pos(rsrc);
- IF module = extract THEN inPackage := TRUE ELSE INC(extrI) END
- END;
- IF inPackage THEN (* pos1 is the position of the rider previous to the entry of the module to be extracted,
- pos2 is the position of the rider after the entry,
- extrI is the index of the module to be extracted.*)
- CreatePackage(fdst, rdst, currPos);
- WriteInt(rdst, nofEntries - 1); currPos := currPos + 2; i := 1;
- Files.Set(rsrc, fsrc, currPos);
- WHILE i <= nofEntries DO
- Files.ReadString(rsrc, module); ReadLInt(rsrc, len); ReadLInt(rsrc, offset);
- IF i # extrI THEN Files.WriteString(rdst, module); WriteLInt(rdst, len) END;
- IF i < extrI THEN
- WriteLInt(rdst, offset - (pos2 - pos1))
- ELSIF i > extrI THEN
- WriteLInt(rdst, offset - (pos2 - pos1) - extrLen)
- END;
- INC(i)
- END;
- copyLen := extrOffset - Files.Pos(rsrc);
- IF copyLen > 0 THEN (* copyLen = 0 when extracting the first module *)
- NEW(buf, copyLen);
- Files.ReadBytes(rsrc, buf^, copyLen); Files.WriteBytes(rdst, buf^, copyLen)
- END;
- Files.Set(rsrc, fsrc, extrOffset + extrLen);
- copyLen := Files.Length(fsrc) - extrOffset - extrLen;
- IF copyLen > 0 THEN (* copyLen = 0 when extracting the last module *)
- NEW(buf, copyLen);
- Files.ReadBytes(rsrc, buf^, copyLen); Files.WriteBytes(rdst, buf^, copyLen)
- END;
- ClosePackage(fdst, newPackage, res);
- AppendObj(extract); fdst := Files.New(extract); Files.Set(rdst, fdst, 0); Files.Set(rsrc, fsrc, extrOffset);
- NEW(buf, extrLen); Files.ReadBytes(rsrc, buf^, extrLen); Files.WriteBytes(rdst, buf^, extrLen);
- Files.Register(fdst)
- END;
- done := (res = 0) & inPackage
- END Extract;
- Syntax10.Scn.Fnt
- VAR entry: Entry; entries: FIFOQueue; nofEntries, i: INTEGER; package, module: ModuleName;
- fsrc, fdst: Files.File; rsrc, rdst: Files.Rider; buf: POINTER TO ARRAY OF CHAR;
- BEGIN
- In.Open; In.Name(package); AppendObj(package);
- IF ~OpenPackage(package, fsrc, rsrc) THEN done := FALSE; RETURN END;
- NEW(entries); InitFIFOQueue(entries);
- ReadInt(rsrc, nofEntries);
- FOR i := 1 TO nofEntries DO
- Files.ReadString(rsrc, module);
- NEW(entry); entries.Enqueue(entry);
- entry.SetName(module); ReadLInt(rsrc, entry.len); ReadLInt(rsrc, entry.offset);
- END;
- WHILE ~entries.Empty() DO
- entry := entries.Dequeue();
- COPY(entry.name^, module); AppendObj(module);
- fdst := Files.New(module); Files.Set(rdst, fdst, 0); NEW(buf, entry.len);
- Files.ReadBytes(rsrc, buf^, entry.len); Files.WriteBytes(rdst, buf^, entry.len);
- Files.Register(fdst);
- END;
- done := TRUE
- END Decompose;
- Syntax10.Scn.Fnt
- VAR package, module: ModuleName; nofEntries, i: INTEGER; len, offset: LONGINT;
- fsrc: Files.File; rsrc: Files.Rider;
- BEGIN
- In.Open; In.Name(package); AppendObj(package);
- Out.Ln; Out.String(package);
- IF ~OpenPackage(package, fsrc, rsrc) THEN Out.String(" is no package."); done := FALSE; RETURN END;
- ReadInt(rsrc, nofEntries);
- Out.String(" contains "); Out.Int(nofEntries, 0); Out.String(" entries."); Out.Ln;
- FOR i := 1 TO nofEntries DO
- Files.ReadString(rsrc, module); ReadLInt(rsrc, len); ReadLInt(rsrc, offset);
- Out.String(module); Out.String(", length: "); Out.Int(len, 0); Out.String(", offset: "); Out.Int(offset, 0); Out.Ln;
- END;
- done := TRUE
- END List;
- PROCEDURE Compose*;
- (**"Packager.Compose {obj}" creates a package out of a list of object files. The names of the object files can either have
- the extension .Mod, .Obj or no extension. The object files must be in the order as they are imported by each other with
- the top-most (user-interface-module with commands) module at the end (like the compile order determined by
- Make.Order). The package gets the name of the last object module.*)
- PROCEDURE Extract*;
- (**"Packager.Extract extr oldPack newPack" extracts the module "extr" from the package "oldPack" and creates the standalone
- object file extr and the new package "newPack" (same as oldPack but without module extr).*)
- PROCEDURE Decompose*;
- (**"Packager.Decompose pack" decomposes the package "pack" into its source object files. Normally the package is deleted
- because when the last module is extracted and created, it has the same name as the module and thus overwrites the
- previously existing package.*)
- PROCEDURE List*;
- (**"Packager.List pack" lists the object files in the package "pack" with their lengths and offsets within the package.*)
- Syntax10.Scn.Fnt
- Folds.Compile A.Mod AA.Mod B.Mod BB.Mod ABB.Mod ~
- Make.Order ^
- Packager.Compose ^ A AA ~ A AA B BB ABB ~ A ~ B BB ~ A AA BB ABB ~
- System.Directory ^ A*.Obj/ds System.Directory B*.Obj/ds New*.Obj/ds
- Packager.List ^
- Packager.Extract ^ A AA B ~ BB ABB NewABB ~ A A B ~
- Packager.Decompose ^ AA ABB A
- ABB.Do A.Do
- Test.Mod Test.Do
- Hex.Open ^ A.Obj AA.Obj B.Obj BB.Obj ABB.Obj
- MODULE Packager;
- (**Christoph Steindl (CS), from 11.01.95 until
- IMPORT In, Out, Files, SYSTEM;
- (** Package file format (simple extension to the PowerPC object file format):
- Package = [Table] {ObjFile}.
- Table = 0F9X "1" nofEntries2 {Name Len4 Offset4}.
- ModuleName = ARRAY 37 OF CHAR;
- Entry = POINTER TO EntryDesc;
- EntryDesc
- FIFOQueue = POINTER TO FIFOQueueDesc;
- QueueElement = POINTER TO QueueElementDesc;
- QueueElementDesc
- FIFOQueueDesc
- done*: BOOLEAN; (** TRUE on success *)
- FIFOQueue handling
- Entry.SetName, AppendObj and SkipObj
- WriteInt, WriteLInt, ReadInt and ReadLInt
- Opening, closing and creation of packages
- Commands: Compose, Decompose, List and Extract
- END Packager.
- For testing only
-